package com.wideplay.crosstalk.services;

import com.google.inject.AbstractModule;
import static com.google.inject.matcher.Matchers.*;
import com.wideplay.crosstalk.tweets.Tweet;
import com.wideplay.crosstalk.web.LoginPage;
import com.wideplay.warp.persist.PersistenceService;
import com.wideplay.warp.persist.UnitOfWork;
import com.wideplay.warp.widgets.Get;
import com.wideplay.warp.widgets.Post;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;

import java.io.IOException;
import java.util.Properties;

/**
 * Installed by CrosstalkModule as the Guice configuration for data
 *  and security services.
 *
 * @author Dhanji R. Prasanna (dhanji@gmail.com)
 */
public final class ServicesModule extends AbstractModule {
    private static final String HIBERNATE_CONFIG = "hibernate.properties";

    @Override
    protected void configure() {

        //configure persistence services, using hibernate
        install(PersistenceService
                .usingHibernate()
                .across(UnitOfWork.REQUEST)
                .buildModule()
        );


        //configure hibernate with our tweet data model class
        bind(Configuration.class).toInstance(new AnnotationConfiguration()
                .addAnnotatedClass(Tweet.class)
                .setProperties(loadProperties(HIBERNATE_CONFIG))
        );

        
        //configure crosstalk data services
        bind(TweetManager.class).to(HibernateTweetManager.class);
        bind(UserManager.class).to(InMemoryUserManager.class);


        //configure the in-memory authenticator (with hard-coded users)
        final HttpSessionAuthenticationManager manager = new HttpSessionAuthenticationManager();
        bind(AuthenticationManager.class).toInstance(manager);


        //intercept any @Get or @Post method on any page except the LoginPage, for security
        bindInterceptor(
                not(subclassesOf(LoginPage.class)),
                annotatedWith(Get.class).or(annotatedWith(Post.class)),

                new SecurityInterceptor(manager)
        );
    }

    private static Properties loadProperties(String props) {
        Properties properties = new Properties();
        try {
            properties.load(ServicesModule.class.getResourceAsStream(props));
        } catch (IOException e) {
            throw new RuntimeException("Could not read " + props);
        }

        return properties;
    }
}
